package com.jijuxie.house.service.impl;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;
import java.util.HashMap;
import java.util.ArrayList;
import java.util.Objects;
import java.util.Comparator;
import java.util.stream.Collectors;
import java.math.BigDecimal;

import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.jijuxie.common.exception.ServiceException;
import com.jijuxie.house.domain.HouseCollection;
import com.jijuxie.house.domain.HouseInfo;
import com.jijuxie.house.domain.HouseImage;
import com.jijuxie.house.domain.HouseFacility;
import com.jijuxie.house.domain.UserHouseCollect;
import com.jijuxie.house.domain.dto.HouseSearchDTO;
import com.jijuxie.house.domain.dto.CollectCountDTO;
import com.jijuxie.house.domain.vo.HouseListVO;
import com.jijuxie.house.domain.vo.HouseMapVO;
import com.jijuxie.house.mapper.HouseCollectionMapper;
import com.jijuxie.house.mapper.HouseImageMapper;
import com.jijuxie.house.mapper.HouseMapper;
import com.jijuxie.house.mapper.UserHouseCollectMapper;
import com.jijuxie.house.service.IHouseImageService;
import com.jijuxie.house.service.IHouseService;
import com.jijuxie.house.service.IHouseAgentService;
import com.jijuxie.house.service.IHouseFacilityService;

import cn.dev33.satoken.stp.StpUtil;
import lombok.extern.slf4j.Slf4j;

@Slf4j
@Service
public class HouseServiceImpl extends ServiceImpl<HouseMapper, HouseInfo> implements IHouseService {

    @Autowired
    private HouseMapper houseMapper;

    @Autowired
    private HouseCollectionMapper collectionMapper;

    @Autowired
    private UserHouseCollectMapper userHouseCollectMapper;

    @Autowired
    private HouseImageMapper houseImageMapper;

    @Autowired
    private IHouseImageService houseImageService;

    @Autowired
    private IHouseAgentService agentService;

    @Autowired
    private IHouseFacilityService houseFacilityService;

    @Override
    public Page<HouseInfo> selectHousePage(Page<HouseInfo> page, HouseInfo houseInfo,
            BigDecimal minPrice, BigDecimal maxPrice,
            BigDecimal minArea, BigDecimal maxArea,
            String sortField, String sortOrder) {
        log.info("查询房源列表，参数：{}", houseInfo);
        
        QueryWrapper<HouseInfo> wrapper = new QueryWrapper<>();
        
        // 添加查询条件
        wrapper.eq("del_flag", "0"); // 只查询未删除的
        if (houseInfo.getHouseType() != null) {
            wrapper.eq("house_type", houseInfo.getHouseType());
        }
        if (houseInfo.getBedroom() != null) {
            wrapper.eq("bedroom", houseInfo.getBedroom());
        }
        if (minPrice != null) {
            wrapper.ge("price", minPrice);
        }
        if (maxPrice != null) {
            wrapper.le("price", maxPrice);
        }
        if (minArea != null) {
            wrapper.ge("area", minArea);
        }
        if (maxArea != null) {
            wrapper.le("area", maxArea);
        }
        
        // 添加排序
        if (sortField != null && !sortField.isEmpty()) {
            // 处理字段名转换
            String dbField = camelToUnderline(sortField);
            boolean isAsc = "asc".equalsIgnoreCase(sortOrder);
            wrapper.orderBy(true, isAsc, dbField);
        } else {
            wrapper.orderByDesc("create_time");
        }
        
        // 分页查询
        Page<HouseInfo> resultPage = baseMapper.selectPage(page, wrapper);
        
        // 获取并设置封面图片
        if (resultPage.getRecords() != null && !resultPage.getRecords().isEmpty()) {
            // 获取所有房源ID
            List<Long> houseIds = resultPage.getRecords().stream()
                    .map(HouseInfo::getHouseId)
                    .collect(Collectors.toList());
            
            // 批量查询封面图片
            List<Map<String, Object>> coverImages = houseMapper.selectHouseCoverImages(houseIds);
            
            // 构建house_id到cover_image的映射
            Map<Long, String> coverImageMap = new HashMap<>();
            for (Map<String, Object> map : coverImages) {
                Long houseId = ((Number) map.get("house_id")).longValue();
                String imageUrl = (String) map.get("image_url");
                coverImageMap.put(houseId, imageUrl);
            }
            
            // 设置封面图片
            for (HouseInfo house : resultPage.getRecords()) {
                house.setCoverImage(coverImageMap.get(house.getHouseId()));
                
                // 如果没有找到封面图片，可能需要确保每个房源有封面图片
                if (house.getCoverImage() == null) {
                    ensureHouseCoverImage(house.getHouseId());
                    
                    // 再次尝试获取封面图片
                    QueryWrapper<HouseImage> imageWrapper = new QueryWrapper<>();
                    imageWrapper.eq("house_id", house.getHouseId())
                            .eq("image_type", "1")
                            .last("LIMIT 1");
                    HouseImage coverImage = houseImageService.getOne(imageWrapper);
                    if (coverImage != null) {
                        house.setCoverImage(coverImage.getImageUrl());
                    }
                }
            }
        }
        
        return resultPage;
    }

    /**
     * 驼峰命名转下划线命名
     * 例如：createTime -> create_time
     */
    private String camelToUnderline(String str) {
        if (str == null || str.trim().isEmpty()) {
            return "";
        }
        int len = str.length();
        StringBuilder sb = new StringBuilder(len);
        for (int i = 0; i < len; i++) {
            char c = str.charAt(i);
            if (Character.isUpperCase(c)) {
                if (i > 0) {
                    sb.append('_');
                }
                sb.append(Character.toLowerCase(c));
            } else {
                sb.append(c);
            }
        }
        return sb.toString();
    }

    @Override
    public Boolean checkCollect(Long houseId, Long userId) {
        QueryWrapper<HouseCollection> wrapper = new QueryWrapper<>();
        wrapper.eq("house_id", houseId)
                .eq("user_id", userId);
        return collectionMapper.selectCount(wrapper) > 0;
    }

    @Override
    public Integer getUserCollectCount(Long userId) {
        QueryWrapper<HouseCollection> wrapper = new QueryWrapper<>();
        wrapper.eq("user_id", userId);
        return collectionMapper.selectCount(wrapper).intValue();
    }

    @Override
    public HouseInfo selectHouseById(Long houseId) {
        // 1. 获取房源基本信息
        HouseInfo house = baseMapper.selectById(houseId);
        if (house == null) {
            return null;
        }

        // 2. 获取房源图片
        QueryWrapper<HouseImage> imageWrapper = new QueryWrapper<>();
        imageWrapper.eq("house_id", houseId)
                .orderByAsc("sort");
        List<HouseImage> images = houseImageService.list(imageWrapper);

        // 设置封面图和其他图片
        if (images != null && !images.isEmpty()) {
            for (HouseImage image : images) {
                if ("1".equals(image.getImageType())) {
                    house.setCoverImage(image.getImageUrl());
                }
            }
            house.setImages(images);
        }

        // 3. 获取配套设施
        List<HouseFacility> facilities = houseFacilityService.selectFacilityList(houseId);
        house.setFacilities(facilities);

        // 4. 获取经纪人详细信息
        if (house.getAgentId() != null) {
            try {
                Map<String, Object> agentInfo = agentService.getAgentDetailInfo(house.getAgentId());
                if (agentInfo != null) {
                    house.setAgentName((String) agentInfo.get("agentName"));
                    house.setAgentAvatar((String) agentInfo.get("avatar"));
                    house.setAgentTitle((String) agentInfo.get("title"));
                    house.setAgentPhone((String) agentInfo.get("phone"));
                    house.setAgentWechat((String) agentInfo.get("wechat"));
                    
                    // 设置经纪人统计信息
                    Map<String, Object> stats = (Map<String, Object>) agentInfo.get("stats");
                    if (stats != null) {
                        house.setAgentStats(stats);
                    }
                }
            } catch (Exception e) {
                log.error("获取经纪人详细信息失败：houseId={}, agentId={}", houseId, house.getAgentId(), e);
            }
        }

        return house;
    }

    /**
     * 设置房源封面图
     * 如果没有封面图（imageType=1），则将第一张图片设置为封面图
     */
    private void ensureHouseCoverImage(Long houseId) {
        // 检查是否已有封面图
        QueryWrapper<HouseImage> coverWrapper = new QueryWrapper<>();
        coverWrapper.eq("house_id", houseId)
                .eq("image_type", "1");
        Long coverCount = houseImageService.count(coverWrapper);
        
        if (coverCount == 0) {
            // 没有封面图，获取第一张图片
            QueryWrapper<HouseImage> firstImageWrapper = new QueryWrapper<>();
            firstImageWrapper.eq("house_id", houseId)
                    .orderByAsc("image_id")
                    .last("LIMIT 1");
            HouseImage firstImage = houseImageService.getOne(firstImageWrapper);
            
            if (firstImage != null) {
                // 将第一张图片设置为封面图
                HouseImage update = new HouseImage();
                update.setImageId(firstImage.getImageId());
                update.setImageType("1");
                houseImageService.updateById(update);
            }
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void insertHouse(HouseInfo houseInfo) {
        // 获取最大排序值
        Integer maxOrder = lambdaQuery()
                .orderByDesc(HouseInfo::getDisplayOrder)
                .last("LIMIT 1")
                .one()
                .getDisplayOrder();

        // 设置新房源的排序值
        houseInfo.setDisplayOrder(maxOrder + 1);

        // 保存房源
        save(houseInfo);
        
        // 确保设置封面图
        ensureHouseCoverImage(houseInfo.getHouseId());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateHouse(HouseInfo houseInfo) {
        boolean success = updateById(houseInfo);
        if (!success) {
            throw new ServiceException("修改房源失败");
        }
        
        // 确保设置封面图
        ensureHouseCoverImage(houseInfo.getHouseId());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteHouse(Long houseId) {
        log.info("开始删除房源，ID：{}", houseId);

        // 1. 验证房源是否存在
        HouseInfo house = lambdaQuery()
                .eq(HouseInfo::getHouseId, houseId)
                .eq(HouseInfo::getDelFlag, "0")
                .one();

        if (house == null) {
            throw new ServiceException("房源不存在");
        }

        // 2. 验证权限
        Long userId = StpUtil.getLoginIdAsLong();
        if (!house.getAgentId().equals(userId) && !StpUtil.hasRole("admin")) {
            throw new ServiceException("无权删除该房源");
        }

        // 3. 使用 MyBatis-Plus 的逻辑删除
        boolean result = removeById(houseId);

        // 4. 更新后续房源的展示顺序
        if (result && house.getDisplayOrder() != null) {
            lambdaUpdate()
                    .setSql("display_order = display_order - 1")
                    .gt(HouseInfo::getDisplayOrder, house.getDisplayOrder())
                    .update();
        }

        log.info("删除房源结果：{}, 房源ID：{}", result, houseId);

        if (!result) {
            throw new ServiceException("删除房源失败");
        }
    }

    @Override
    public void changeStatus(Long houseId, String status) {
        HouseInfo house = getById(houseId);
        if (house == null) {
            throw new ServiceException("房源不存在");
        }

        // 状态流转验证
        switch (status) {
            case "2": // 下架
                if (!"1".equals(house.getStatus())) {
                    throw new ServiceException("只有已上架的房源才能下架");
                }
                break;
            case "1": // 重新上架
                if (!"2".equals(house.getStatus())) {
                    throw new ServiceException("只有已下架的房源才能重新上架");
                }
                // 重新上架需要重新审核
                status = "0";  // 改为待审核状态
                break;
            case "3": // 成交（暂不开放）
                throw new ServiceException("成交功能暂未开放");
            case "0": // 不允许直接修改为待审核状态
                throw new ServiceException("不能直接修改为待审核状态");
            default:
                throw new ServiceException("状态值不正确（1:上架 2:下架）");
        }

        HouseInfo update = new HouseInfo();
        update.setHouseId(houseId);
        update.setStatus(status);
        update.setUpdateTime(LocalDateTime.now());
        update.setUpdateBy(StpUtil.getLoginIdAsString());

        if (!updateById(update)) {
            throw new ServiceException("修改房源状态失败");
        }

        log.info("房源状态修改成功：houseId={}, status={}", houseId, status);
    }

    @Override
    public Page<HouseInfo> searchHousePage(Page<HouseInfo> page, HouseSearchDTO searchDTO) {
        return page.setRecords(houseMapper.searchHouseList(searchDTO));
    }

    @Override
    public void collectHouse(Long houseId, Long userId) {
        // 1. 检查房源是否存在
        HouseInfo house = getById(houseId);
        if (house == null) {
            throw new ServiceException("房源不存在");
        }

        // 2. 检查是否已收藏
        QueryWrapper<UserHouseCollect> wrapper = new QueryWrapper<>();
        wrapper.eq("house_id", houseId)
                .eq("user_id", userId)
                .eq("status", "1");
        if (userHouseCollectMapper.selectCount(wrapper) > 0) {
            throw new ServiceException("已收藏该房源");
        }

        // 3. 检查是否有取消的收藏记录
        wrapper = new QueryWrapper<>();
        wrapper.eq("house_id", houseId)
                .eq("user_id", userId)
                .eq("status", "0")
                .orderByDesc("collect_time")
                .last("LIMIT 1");
        UserHouseCollect oldCollect = userHouseCollectMapper.selectOne(wrapper);
        
        LocalDateTime now = LocalDateTime.now();
        
        if (oldCollect != null) {
            // 4a. 如果有取消的收藏记录，更新状态和时间
            oldCollect.setStatus("1");
            oldCollect.setCollectTime(now);  // 更新为新的收藏时间
            oldCollect.setUpdateTime(now);
            userHouseCollectMapper.updateById(oldCollect);
        } else {
            // 4b. 如果没有历史记录，创建新记录
            UserHouseCollect collect = new UserHouseCollect();
            collect.setHouseId(houseId);
            collect.setUserId(userId);
            collect.setCollectTime(now);
            collect.setCreateTime(now);
            collect.setUpdateTime(now);
            collect.setStatus("1");
            userHouseCollectMapper.insert(collect);
        }

        // 5. 更新房源收藏数
        lambdaUpdate()
                .setSql("collect_count = collect_count + 1")
                .eq(HouseInfo::getHouseId, houseId)
                .update();
    }

    @Override
    public void cancelCollect(Long houseId, Long userId) {
        // 1. 检查房源是否存在
        HouseInfo house = getById(houseId);
        if (house == null) {
            throw new ServiceException("房源不存在");
        }

        // 2. 更新收藏记录状态为已取消
        UserHouseCollect collect = new UserHouseCollect();
        collect.setStatus("0");
        collect.setUpdateTime(LocalDateTime.now());
        
        QueryWrapper<UserHouseCollect> wrapper = new QueryWrapper<>();
        wrapper.eq("house_id", houseId)
                .eq("user_id", userId)
                .eq("status", "1");
                
        if (userHouseCollectMapper.update(collect, wrapper) > 0) {
            // 3. 更新房源收藏数
            lambdaUpdate()
                    .setSql("collect_count = GREATEST(collect_count - 1, 0)") // 使用 GREATEST 确保不会小于0
                    .eq(HouseInfo::getHouseId, houseId)
                    .update();
        }
    }

    @Override
    public Page<HouseInfo> selectCollectPage(Page<HouseInfo> page, Long userId) {
        return page.setRecords(houseMapper.selectCollectList(userId));
    }

    @Override
    public List<HouseInfo> selectRecommendList(Long userId) {
        return lambdaQuery()
                .eq(HouseInfo::getStatus, "0")
                .orderByDesc(HouseInfo::getCreateTime)
                .last("limit 10")
                .list();
    }

    @Override
    public HouseMapVO selectMapInfo(Long houseId) {
        HouseInfo houseInfo = getById(houseId);
        if (houseInfo == null) {
            throw new ServiceException("房源不存在");
        }
        HouseMapVO mapVO = new HouseMapVO();
        BeanUtils.copyProperties(houseInfo, mapVO);
        return mapVO;
    }

    @Override
    public List<HouseMapVO> selectAreaHouses(Double minLng, Double maxLng, Double minLat, Double maxLat) {
        return lambdaQuery()
                .ge(HouseInfo::getLng, minLng)
                .le(HouseInfo::getLng, maxLng)
                .ge(HouseInfo::getLat, minLat)
                .le(HouseInfo::getLat, maxLat)
                .eq(HouseInfo::getStatus, "1") // 只查询已上架的
                .eq(HouseInfo::getDelFlag, "0") // 只查询未删除的
                .list()
                .stream()
                .map(house -> {
                    HouseMapVO mapVO = new HouseMapVO();
                    BeanUtils.copyProperties(house, mapVO);
                    return mapVO;
                })
                .collect(Collectors.toList());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void auditHouse(Long houseId, String status, Long auditorId) {
        log.info("开始审核房源：houseId={}, status={}, auditorId={}", houseId, status, auditorId);
        HouseInfo house = getById(houseId);
        if (house == null) {
            throw new ServiceException("房源不存在");
        }
        // 只能审核待审核状态的房源（状态值为0）
        if (!"0".equals(house.getStatus())) {
            throw new ServiceException("房源状态不正确，只能审核待审核的房源");
        }
        // 只能审核为通过(1)或不通过(4)
        if (!"1".equals(status) && !"4".equals(status)) {
            throw new ServiceException("审核状态值不正确，只能为通过或不通过");
        }
        HouseInfo update = new HouseInfo();
        update.setHouseId(houseId);
        // 设置房源状态
        update.setStatus(status);
        // 不再设置audit_status字段，只使用status字段
        // 设置审核备注和时间、审核人
        update.setAuditRemark(house.getAuditRemark()); // 前端已传入remark字段
        update.setAuditTime(LocalDateTime.now());
        update.setAuditorId(auditorId);
        update.setUpdateTime(LocalDateTime.now());
        update.setUpdateBy(auditorId.toString());
        if (!updateById(update)) {
            throw new ServiceException("审核房源失败");
        }
        log.info("房源审核成功：houseId={}, newStatus={}", houseId, status);
    }

    @Override
    public Page<HouseInfo> selectDeletedHousePage(Page<HouseInfo> page, HouseInfo houseInfo) {
        log.info("开始查询已删除房源列表");
        return baseMapper.selectDeletedPage(page);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void restoreHouse(Long houseId) {
        log.info("开始恢复已删除房源，ID：{}", houseId);

        int rows = baseMapper.restoreHouse(
                houseId,
                LocalDateTime.now(),
                StpUtil.getLoginIdAsString()
        );

        log.info("恢复房源结果：rows={}", rows);

        if (rows == 0) {
            throw new ServiceException("房源不存在或未被删除");
        }

        log.info("房源恢复成功");
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void cleanDeletedHouses() {
        log.info("开始清理7天前删除的房源");

        LocalDateTime sevenDaysAgo = LocalDateTime.now().minusDays(7);

        // 查找需要清理的房源
        List<HouseInfo> housesToDelete = lambdaQuery()
                .eq(HouseInfo::getDelFlag, "1")
                .le(HouseInfo::getUpdateTime, sevenDaysAgo)
                .list();

        if (!housesToDelete.isEmpty()) {
            // 物理删除这些房源
            List<Long> houseIds = housesToDelete.stream()
                    .map(HouseInfo::getHouseId)
                    .collect(Collectors.toList());

            this.removeBatchByIds(houseIds);

            // 重新排序house_id
            String resetAutoIncrementSql = "ALTER TABLE house_info AUTO_INCREMENT = 1";
            baseMapper.deleteBatchIds(houseIds);  // 先删除
            baseMapper.update(null, new UpdateWrapper<HouseInfo>().setSql(resetAutoIncrementSql));  // 重置自增值

            log.info("已清理{}个7天前删除的房源", housesToDelete.size());
        }
    }

    @Override
    public Page<HouseInfo> selectHotHousePage(Page<HouseInfo> page) {
        log.info("查询热门房源列表");
        Page<HouseInfo> resultPage = lambdaQuery()
                .eq(HouseInfo::getStatus, "1") // 只查询已上架的房源
                .eq(HouseInfo::getDelFlag, "0") // 只查询未删除的房源
                .orderByDesc(HouseInfo::getCollectCount) // 按收藏数降序排序
                .orderByDesc(HouseInfo::getCreateTime) // 相同收藏数时，按创建时间降序
                .page(page);
        
        // 获取并设置封面图片
        if (resultPage.getRecords() != null && !resultPage.getRecords().isEmpty()) {
            List<Long> houseIds = resultPage.getRecords().stream()
                    .map(HouseInfo::getHouseId)
                    .collect(Collectors.toList());
            
            // 批量查询封面图片
            List<Map<String, Object>> coverImages = houseMapper.selectHouseCoverImages(houseIds);
            
            // 构建house_id到cover_image的映射
            Map<Long, String> coverImageMap = new HashMap<>();
            for (Map<String, Object> map : coverImages) {
                Long houseId = ((Number) map.get("house_id")).longValue();
                String imageUrl = (String) map.get("image_url");
                coverImageMap.put(houseId, imageUrl);
            }
            
            // 设置封面图片
            for (HouseInfo house : resultPage.getRecords()) {
                house.setCoverImage(coverImageMap.get(house.getHouseId()));
                
                // 如果没有找到封面图片，可能需要确保每个房源有封面图片
                if (house.getCoverImage() == null) {
                    ensureHouseCoverImage(house.getHouseId());
                    
                    // 再次尝试获取封面图片
                    QueryWrapper<HouseImage> imageWrapper = new QueryWrapper<>();
                    imageWrapper.eq("house_id", house.getHouseId())
                            .eq("image_type", "1")
                            .last("LIMIT 1");
                    HouseImage coverImage = houseImageService.getOne(imageWrapper);
                    if (coverImage != null) {
                        house.setCoverImage(coverImage.getImageUrl());
                    }
                }
            }
        }
        
        return resultPage;
    }

    @Override
    public Page<HouseInfo> selectLatestHousePage(Page<HouseInfo> page) {
        log.info("查询最新房源列表");
        Page<HouseInfo> resultPage = lambdaQuery()
                .eq(HouseInfo::getStatus, "1") // 只查询已上架的房源
                .eq(HouseInfo::getDelFlag, "0") // 只查询未删除的房源
                .orderByDesc(HouseInfo::getCreateTime) // 按创建时间降序排序
                .page(page);
        
        // 获取并设置封面图片
        if (resultPage.getRecords() != null && !resultPage.getRecords().isEmpty()) {
            List<Long> houseIds = resultPage.getRecords().stream()
                    .map(HouseInfo::getHouseId)
                    .collect(Collectors.toList());
            
            // 批量查询封面图片
            List<Map<String, Object>> coverImages = houseMapper.selectHouseCoverImages(houseIds);
            
            // 构建house_id到cover_image的映射
            Map<Long, String> coverImageMap = new HashMap<>();
            for (Map<String, Object> map : coverImages) {
                Long houseId = ((Number) map.get("house_id")).longValue();
                String imageUrl = (String) map.get("image_url");
                coverImageMap.put(houseId, imageUrl);
            }
            
            // 设置封面图片
            for (HouseInfo house : resultPage.getRecords()) {
                house.setCoverImage(coverImageMap.get(house.getHouseId()));
                
                // 如果没有找到封面图片，可能需要确保每个房源有封面图片
                if (house.getCoverImage() == null) {
                    ensureHouseCoverImage(house.getHouseId());
                    
                    // 再次尝试获取封面图片
                    QueryWrapper<HouseImage> imageWrapper = new QueryWrapper<>();
                    imageWrapper.eq("house_id", house.getHouseId())
                            .eq("image_type", "1")
                            .last("LIMIT 1");
                    HouseImage coverImage = houseImageService.getOne(imageWrapper);
                    if (coverImage != null) {
                        house.setCoverImage(coverImage.getImageUrl());
                    }
                }
            }
        }
        
        return resultPage;
    }

    @Override
    public Page<HouseListVO> selectHotHouseDetailPage(Page<HouseListVO> page) {
        log.info("查询热门房源列表");
        Long userId = StpUtil.getLoginIdAsLong();
        List<HouseListVO> list = baseMapper.selectHouseListWithDetail(userId, true);
        return page.setRecords(list);
    }

    @Override
    public Page<HouseListVO> selectLatestHouseDetailPage(Page<HouseListVO> page) {
        log.info("查询最新房源列表");
        Long userId = StpUtil.getLoginIdAsLong();
        List<HouseListVO> list = baseMapper.selectHouseListWithDetail(userId, false);
        return page.setRecords(list);
    }

    /**
     * 根据条件统计收藏数量
     */
    @Override
    public Integer countCollects(CollectCountDTO dto) {
        return (int) countCollectsByCondition(dto);
    }

    @Override
    public long countCollectsByCondition(CollectCountDTO countDTO) {
        // 判断是否需要关联房源表
        boolean needJoinHouse = countDTO.getProvince() != null || countDTO.getCity() != null || 
                               countDTO.getDistrict() != null || countDTO.getPropertyType() != null;
        
        return userHouseCollectMapper.countCollectsByCondition(countDTO, needJoinHouse);
    }

    @Override
    public List<Map<String, Object>> countCollectsInDateRange(Long userId, LocalDateTime startTime, LocalDateTime endTime) {
        return userHouseCollectMapper.countCollectsByDateRange(userId, startTime, endTime);
    }

    @Override
    public List<Map<String, Object>> getDailyCollectCounts(Long userId, LocalDateTime startTime, LocalDateTime endTime) {
        return userHouseCollectMapper.selectDailyCollectCounts(userId, startTime, endTime);
    }

    @Override
    public Page<HouseMapVO> selectNearbyHouses(Double lng, Double lat, Double radius, Page<HouseMapVO> page) {
        log.info("查询附近房源，经度:{}, 纬度:{}, 半径:{}米", lng, lat, radius);
        
        // 计算经纬度范围（粗略计算）
        // 纬度：1度约等于111公里
        Double latRange = radius / 111000;
        // 经度：1度约等于111公里 * cos(纬度)
        Double lngRange = radius / (111000 * Math.cos(Math.toRadians(lat)));
        
        Double minLng = lng - lngRange;
        Double maxLng = lng + lngRange;
        Double minLat = lat - latRange;
        Double maxLat = lat + latRange;
        
        log.info("计算经纬度范围：经度[{} - {}], 纬度[{} - {}]", minLng, maxLng, minLat, maxLat);
        
        // 先查询矩形区域内的房源
        List<HouseInfo> houses = lambdaQuery()
                .ge(HouseInfo::getLng, minLng)
                .le(HouseInfo::getLng, maxLng)
                .ge(HouseInfo::getLat, minLat)
                .le(HouseInfo::getLat, maxLat)
                .eq(HouseInfo::getStatus, "1") // 只查询已上架的
                .eq(HouseInfo::getDelFlag, "0") // 只查询未删除的
                .list();
        
        log.info("矩形区域内找到{}个房源", houses.size());
        
        // 进一步筛选真正在圆形范围内的房源并计算距离
        List<Map<String, Object>> houseWithDistance = houses.stream()
                .map(house -> {
                    // 计算距离
                    Double distance = calculateDistance(
                            lng, lat, 
                            house.getLng().doubleValue(), 
                            house.getLat().doubleValue());
                    
                    // 只返回指定半径内的房源
                    if (distance <= radius) {
                        Map<String, Object> map = new HashMap<>();
                        map.put("house", house);
                        map.put("distance", distance);
                        return map;
                    }
                    return null;
                })
                .filter(Objects::nonNull)
                // 按距离排序
                .sorted(Comparator.comparing(map -> (Double) map.get("distance")))
                .collect(Collectors.toList());
        
        // 分页处理
        int start = (int) ((page.getCurrent() - 1) * page.getSize());
        int end = Math.min(houseWithDistance.size(), start + (int)page.getSize());
        
        List<HouseMapVO> records = new ArrayList<>();
        if (start < houseWithDistance.size()) {
            records = houseWithDistance.subList(start, end).stream()
                    .map(map -> {
                        HouseInfo house = (HouseInfo) map.get("house");
                        Double distance = (Double) map.get("distance");
                        HouseMapVO mapVO = new HouseMapVO();
                        BeanUtils.copyProperties(house, mapVO);
                        // 设置与中心点的距离（米）
                        mapVO.setDistance(distance);
                        return mapVO;
                    })
                    .collect(Collectors.toList());
        }
        
        Page<HouseMapVO> result = new Page<>(page.getCurrent(), page.getSize());
        result.setRecords(records);
        result.setTotal(houseWithDistance.size());
        
        return result;
    }
    
    /**
     * 计算两点之间的距离（米）
     * 使用Haversine公式计算球面距离
     */
    private Double calculateDistance(Double lng1, Double lat1, Double lng2, Double lat2) {
        final double EARTH_RADIUS = 6371000; // 地球半径，单位：米
        
        double dLat = Math.toRadians(lat2 - lat1);
        double dLng = Math.toRadians(lng2 - lng1);
        
        double a = Math.sin(dLat / 2) * Math.sin(dLat / 2) + 
                Math.cos(Math.toRadians(lat1)) * Math.cos(Math.toRadians(lat2)) * 
                Math.sin(dLng / 2) * Math.sin(dLng / 2);
        double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
        
        return EARTH_RADIUS * c;
    }

    /**
     * 批量更新所有房源的封面图片
     * 此方法将为所有没有封面图片的房源设置第一张图片作为封面图片
     */
    @Transactional(rollbackFor = Exception.class)
    public void updateAllHouseCoverImages() {
        log.info("开始批量更新所有房源的封面图片");
        
        // 查询所有未删除的房源
        List<HouseInfo> allHouses = lambdaQuery()
                .eq(HouseInfo::getDelFlag, "0")
                .list();
        
        int updatedCount = 0;
        
        for (HouseInfo house : allHouses) {
            // 检查是否已有封面图
            QueryWrapper<HouseImage> coverWrapper = new QueryWrapper<>();
            coverWrapper.eq("house_id", house.getHouseId())
                    .eq("image_type", "1");
            Long coverCount = houseImageService.count(coverWrapper);
            
            if (coverCount == 0) {
                // 没有封面图，获取第一张图片
                QueryWrapper<HouseImage> firstImageWrapper = new QueryWrapper<>();
                firstImageWrapper.eq("house_id", house.getHouseId())
                        .orderByAsc("image_id")
                        .last("LIMIT 1");
                HouseImage firstImage = houseImageService.getOne(firstImageWrapper);
                
                if (firstImage != null) {
                    // 将第一张图片设置为封面图
                    HouseImage update = new HouseImage();
                    update.setImageId(firstImage.getImageId());
                    update.setImageType("1");
                    boolean success = houseImageService.updateById(update);
                    if (success) {
                        updatedCount++;
                    }
                }
            }
        }
        
        log.info("批量更新房源封面图片完成，更新了{}个房源", updatedCount);
    }
}
